package com.yxy.http;

import com.yxy.http.util.MD5Util;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.text.SimpleDateFormat;

/**
 * 客户端数据发送类。
 */
public final class Client {
    private final Logger logger = LogManager.getLogger();

    /**
     * HttpClient与SpringBoot数据交互，上传文件
     * @param url
     * @param file
     * @return
     */
    public String uploadFile(String url,File file) {
        /**
         * keepalive策略 设置长连接
         */
        ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                // Honor 'keep-alive' header
                HeaderElementIterator it = new BasicHeaderElementIterator(
                        response.headerIterator(HTTP.CONN_KEEP_ALIVE));
                while (it.hasNext()) {
                    HeaderElement he = it.nextElement();
                    String param = he.getName();
                    String value = he.getValue();
                    if (value != null && param.equalsIgnoreCase("timeout")) {
                        try {
                            return Long.parseLong(value) * 1000;
                        } catch (NumberFormatException ignore) {
                        }
                    }
                }
                HttpHost target = (HttpHost) context.getAttribute(
                        HttpClientContext.HTTP_TARGET_HOST);
                if ("www.baidu.com".equalsIgnoreCase(target.getHostName())) {
                    return 5 * 1000;
                } else {
                    return 60 * 1000;
                }
            }
        };
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        logger.info("客户端发送任务开始，当前系统时间为:" + df.format(System.currentTimeMillis()));
        //创建httpClient短连接实例
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //创建httpClient长连接实例
        /*CloseableHttpClient httpclient = HttpClients.custom()
                .setKeepAliveStrategy(myStrategy)
                .build();*/
        CloseableHttpResponse response = null;
        String result = null;
        try {
            //创建httpPost远程连接实例
            HttpPost httpPost = new HttpPost(url);
            String md5ByFile = MD5Util.getMd5ByFile(file);
            httpPost.addHeader("signFile", md5ByFile);
            //使用MultipartEntityBuilder传递文件
            MultipartEntityBuilder mEntityBuilder = MultipartEntityBuilder.create();
            //将文件封装到这个MultipartEntityBuilder里面
            mEntityBuilder.addBinaryBody("file", file);
            httpPost.setEntity(mEntityBuilder.build());
            //执行post请求得到返回对象
            response = httpclient.execute(httpPost);
            //通过返回对象获取请求状态码
            int statusCode = response.getStatusLine().getStatusCode();
            //验证请求状态
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity resEntity = response.getEntity();
                result = EntityUtils.toString(resEntity);
                // 消耗掉response
                EntityUtils.consume(resEntity);
            }
            logger.info("客户端文件传送任务结束，当前系统时间为:" + df.format(System.currentTimeMillis()));
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (null != response) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpclient) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


    /**
     * httpClient与Springboot交互，下载文件
     * @param url
     */
    public void download(String url) {
        HttpClient httpClient = null;
        HttpResponse response = null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            //创建httpClient实例
            httpClient = HttpClients.createDefault();
            //创建httpPost远程连接实例
            HttpPost httpPost = new HttpPost(url);
            logger.info("发起下载请求：" + df.format(System.currentTimeMillis()));
            //执行post请求得到返回对象
            response = httpClient.execute(httpPost);
            //通过返回对象获取数据,将数据封装到流里面
            InputStream inputStream = response.getEntity().getContent();
            //获取响应头信息
            Header[] heaher = response.getHeaders("sign");
            logger.info("接收到响应，开始读取响应数据：" + df.format(System.currentTimeMillis()));
            if(inputStream==null){
                logger.info("空数据");
                return;
            }
            //将流转到字节流数组里存储
            byte[] bytes1 = IOUtils.toByteArray(inputStream);
            logger.info("读取数据结束，生成MD5检验码：" + df.format(System.currentTimeMillis()));
            //通过DigestUtils生成MD5校验码
            String md5 = DigestUtils.md5Hex(bytes1);
            //关闭流
            String sign = heaher[0].toString().substring(6);
            if(!StringUtils.equalsIgnoreCase(sign,md5)){
                logger.info("校验失败");
                return;
            }
            logger.info("校验结束，开始写盘操作：" + df.format(System.currentTimeMillis()));
            //本地磁盘写入的文件名
            String fileName = "E:/aaa.zip";
            File file = new File(fileName);//创建一个新文件
            if (!file.exists()) {
                file.createNewFile();
            }
            OutputStream os = new FileOutputStream(file);
            int i = 0;
            byte[] temp = new byte[1024*1024*100];
            while ((i = inputStream.read(temp)) > 0) {
                byte[] bytes = new byte[i];
                System.arraycopy(temp, 0, bytes, 0, i);
                os.write(bytes);
            }
            os.flush();
            logger.info("写盘结束，当前时间为：" + df.format(System.currentTimeMillis()));

        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("写入到本地的时间段：" + df.format(System.currentTimeMillis()));
    }

}
